package com.personal.system.controller.act;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.personal.common.result.Result;
import com.personal.system.entity.FormData;
import com.personal.system.mapper.act.ActivitiMapper;
import com.personal.system.mapper.act.FormDataMapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.activiti.api.process.model.ProcessInstance;
import org.activiti.api.process.runtime.ProcessRuntime;
import org.activiti.api.runtime.shared.query.Page;
import org.activiti.api.runtime.shared.query.Pageable;
import org.activiti.api.task.model.Task;
import org.activiti.api.task.model.builders.TaskPayloadBuilder;
import org.activiti.api.task.runtime.TaskRuntime;
import org.activiti.bpmn.model.FormProperty;
import org.activiti.bpmn.model.UserTask;
import org.activiti.engine.RepositoryService;
import org.apache.commons.lang3.BooleanUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@RestController
@RequestMapping("/act/task")
public class TaskController {
    @Resource
    private TaskRuntime taskRuntime;

    @Resource
    private FormDataMapper formDataMapper;

    @Resource
    private ProcessRuntime processRuntime;

    @Resource
    private RepositoryService repositoryService;

    @Resource
    private ActivitiMapper mapper;

    //获取我的代办任务
    @GetMapping(value = "/getTasks/{page}/{limit}")
    public Result getTasks(@PathVariable int page, @PathVariable int limit) {
        try {
            Page<Task> tasks = taskRuntime.tasks(Pageable.of(page - 1, limit));

            List<HashMap<String, Object>> listMap = new ArrayList<>();

            for (Task tk : tasks.getContent()) {
                ProcessInstance processInstance = processRuntime.processInstance(tk.getProcessInstanceId());
                HashMap<String, Object> hashMap = new HashMap<>();
                hashMap.put("id", tk.getId());
                hashMap.put("name", tk.getName());
                hashMap.put("status", tk.getStatus());
                hashMap.put("createdDate", tk.getCreatedDate());
                if (tk.getAssignee() == null) {//执行人，null时前台显示未拾取
                    hashMap.put("assignee", "待拾取任务");
                } else {
                    hashMap.put("assignee", tk.getAssignee());//
                }

                hashMap.put("instanceName", processInstance.getName());
                listMap.add(hashMap);
            }
            Map<String, Object> map = new HashMap<>();
            map.put("listMap", listMap);
            map.put("total", tasks.getTotalItems());

            return Result.ok(map);
        } catch (Exception e) {
            return Result.fail("获取我的代办任务失败");
        }
    }

    //完成待办任务
    @GetMapping(value = "/completeTask")
    public Result completeTask(@RequestParam("taskID") String taskID) {
        try {
            Task task = taskRuntime.task(taskID);

            if (task.getAssignee() == null) {
                taskRuntime.claim(TaskPayloadBuilder.claim().withTaskId(task.getId()).build());
            }
            Task compTask = taskRuntime.complete(TaskPayloadBuilder.complete().withTaskId(task.getId())
                    //.withVariable("num", "2")//执行环节设置变量
                    .build());

            return Result.ok(compTask);
        } catch (Exception e) {
            return Result.fail("完成失败");
        }
    }

    //    //启动
//    @GetMapping(value = "/startProcess4")
//    public AjaxResponse startProcess3(@RequestParam("processDefinitionKey") String processDefinitionKey,
//                                      @RequestParam("instanceName") String instanceName,
//                                      @RequestParam("instanceVariable") String instanceVariable) {
//        try {
//            if (GlobalConfig.Test) {
//                securityUtil.logInAs("wukong");
//            }
//
//
///*            @RequestMapping("/approval_msg")
//            @ResponseBody
//            public JsonResponse approvalPass(String id,String msg){
//                JsonResponse jsonResponse = new JsonResponse();
//
//                if(StringUtil.isNotEmpty(msg)){
//                    String str= msg.replace("\"", "");
//                    taskService.setVariable(id,"msg",str);
//                }
//                taskService.complete(id);
//                return jsonResponse;
//            }*/
//
//            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
//                    GlobalConfig.ResponseCode.SUCCESS.getDesc(), null);
//        } catch (Exception e) {
//            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
//                    "失败", e.toString());
//        }
//    }
//
//
    //渲染表单
    @GetMapping(value = "/formDataShow")
    public Result formDataShow(@RequestParam("taskID") String taskID) {
        try {
            Task task = taskRuntime.task(taskID);

//-----------------------构建表单控件历史数据字典------------------------------------------------
            //本实例所有保存的表单数据HashMap，为了快速读取控件以前环节存储的值
            HashMap<String, String> controlistMap = new HashMap<>();
            //本实例所有保存的表单数据
            List<FormData> tempControlList = formDataMapper.selectList(
                    Wrappers.lambdaQuery(FormData.class).eq(FormData::getProcInstId, taskID));

            for (FormData ls : tempControlList) {
                controlistMap.put(ls.getControlId(), ls.getControlValue());
            }
            //String controlistMapValue = controlistMap.get("控件ID");
            //controlistMap.containsKey()

/*  ------------------------------------------------------------------------------
            FormProperty_0ueitp2-_!类型-_!名称-_!默认值-_!是否参数
            例子：
            FormProperty_1gacce1-_!string-_!姓名-_!请输入姓名-_!f
            FormProperty_3pf00q8-_!string-_!年龄-_!请输入年龄-_!s

            默认值：无、字符常量、FormProperty_开头定义过的控件ID
            是否参数：f为不是参数，s是字符，t是时间(不需要int，因为这里int等价于string)
            注：类型是可以获取到的，但是为了统一配置原则，都配置到
            */

            //注意!!!!!!!!:表单Key必须要任务编号一模一样，因为参数需要任务key，但是无法获取，只能获取表单key“task.getFormKey()”当做任务key
            UserTask userTask = (UserTask) repositoryService.getBpmnModel(task.getProcessDefinitionId())
                    .getFlowElement(task.getFormKey());
            if (userTask == null) {
                this.completeTask(taskID);
                return Result.ok("无表单完成！");
            }
            List<FormProperty> formProperties = userTask.getFormProperties();

            List<FormData> listMap = new ArrayList<>();
            for (FormProperty fp : formProperties) {
                String[] splitFP = fp.getId().split("-_!");
                FormData formData = new FormData();

//                hashMap.put("id", splitFP[0]);
                formData.setControlId(splitFP[0]);
//                hashMap.put("controlType", splitFP[1]);
                formData.setControlType(splitFP[1]);
//                hashMap.put("controlLable", splitFP[2]);
                formData.setControlName(splitFP[2]);

                //默认值如果是表单控件ID
                if (splitFP[3].startsWith("FormProperty_")) {
                    //控件ID存在
                    if (controlistMap.containsKey(splitFP[3])) {
//                        hashMap.put("controlDefValue", controlistMap.get(splitFP[3]));
                        formData.setControlValue(controlistMap.get(splitFP[3]));
                    } else {
                        //控件ID不存在
//                        hashMap.put("controlDefValue", "读取失败，检查" + splitFP[0] + "配置");
                        formData.setControlValue("读取失败，检查" + splitFP[0] + "配置");
                    }
                } else {
                    //默认值如果不是表单控件ID则写入默认值
//                    hashMap.put("controlDefValue", splitFP[3]);
                    formData.setControlValue(splitFP[3]);
                }
                formData.setControlIsParam(splitFP[4]);
//                hashMap.put("controlIsParam", splitFP[4]);
                listMap.add(formData);
            }

            return Result.ok(listMap);
        } catch (Exception e) {
            e.printStackTrace();
            return Result.fail().message("失败:" + e.getMessage());
        }
    }

    //保存表单
    @PostMapping(value = "/formDataSave")
    public Result formDataSave(@RequestBody Map<String, Object> map) {
        try {
            String taskID = map.get("taskID").toString();
            List<FormData> formData = JSONArray.parseArray(JSON.toJSONString(map.get("formData")), FormData.class);
            Task task = taskRuntime.task(taskID);

            //formData:控件id-_!控件值-_!是否参数!_!控件id-_!控件值-_!是否参数
            //FormProperty_0lovri0-_!不是参数-_!f!_!FormProperty_1iu6onu-_!数字参数-_!s

            HashMap<String, Object> variables = new HashMap<>();
            Boolean hasVariables = false;//没有任何参数

            List<FormData> listMap = new ArrayList<>();

            //前端传来的字符串，拆分成每个控件
//            String[] formDataList = formData.toString().split("!_!");//
            for (FormData controlItem : formData) {
//                String[] formDataItem = controlItem.split("-_!");
//                HashMap<String, Object> hashMap = new HashMap<>();
//                hashMap.put("PROC_DEF_ID_", task.getProcessDefinitionId());
//                hashMap.put("PROC_INST_ID_", task.getProcessInstanceId());
//                hashMap.put("FORM_KEY_", task.getFormKey());
//                hashMap.put("Control_ID_", controlItem.get("id"));
//                hashMap.put("Control_VALUE_", controlItem.get("controlDefValue"));
//                listMap.add(hashMap);

                FormData form = new FormData();
                form.setProcDefId(task.getProcessDefinitionId());
                form.setProcInstId(task.getProcessInstanceId());
                form.setFormKey(task.getFormKey());
                form.setControlId(controlItem.getControlId());
                form.setTaskNodeName(task.getAssignee());

                //构建参数集合
                String cid = controlItem.getControlId();
                String controlValue = controlItem.getControlValue();
                String controlIsParam = controlItem.getControlIsParam();
                form.setControlType(controlItem.getControlType());
                form.setControlName(controlItem.getControlName());
                form.setControlIsParam(controlIsParam);

                listMap.add(form);
                switch (controlIsParam) {
                    case "f":
                        System.out.println("控件值不作为参数");
                        break;
                    case "s":
                        variables.put(cid, controlValue);
                        hasVariables = true;
                        break;
                    case "t":
                        SimpleDateFormat timeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
                        variables.put(cid, timeFormat.parse(controlValue));
                        hasVariables = true;
                        break;
                    case "b":
                        variables.put(cid, BooleanUtils.toBoolean(controlIsParam));
                        hasVariables = true;
                        break;
                    default:
                        return Result.fail().message("控件参数类型配置错误：" + cid + "的参数类型不存在，" + controlIsParam);
                }
                controlValue = controlValue.equals("0") ? "同意" : controlValue.equals("1") ? "不同意" : controlValue;
                form.setControlValue(controlValue);
            }

            if (task.getAssignee() == null) {
                taskRuntime.claim(TaskPayloadBuilder.claim().withTaskId(task.getId()).build());
            }

            if (hasVariables) {
                //带参数完成任务
                taskRuntime.complete(TaskPayloadBuilder.complete().withTaskId(taskID)
                        .withVariables(variables).build());
            } else {
                taskRuntime.complete(TaskPayloadBuilder.complete().withTaskId(taskID).build());
            }

            //写入数据库
            listMap.forEach(formDataMapper::insert);

            return Result.ok(listMap);
        } catch (Exception e) {
            e.printStackTrace();
            return Result.fail().message("失败:" + e.toString());
        }
    }

}
